<template>
  <div class="image-upload">
    <!-- 上传区域 -->
    <div ref="dropZone" class="upload-zone" :class="{
        'upload-zone--dragover': isDragOver,
        'upload-zone--disabled': disabled || isUploading,
        'upload-zone--grid': layout === 'grid'
      }"
         @click="handleClickUpload"
         @drop="handleDrop"
         @dragover="handleDragOver"
         @dragleave="handleDragLeave">
      <!-- 网格布局：显示已上传的图片 -->
      <template v-if="layout === 'grid'">
        <div class="image-grid">
          <!-- 已上传的图片 -->
          <div v-for="(image, index) in completedFiles" :key="image.id" class="image-item">
            <div class="image-wrapper">
              <img :src="image.previewUrl || image.url" :alt="image.name" class="image-preview"
                   @click.stop="previewImage(image, index)"/>
              <div class="image-overlay">
                <div class="image-actions">
                  <el-button type="primary" :icon="View" circle size="small" @click.stop="previewImage(image, index)"/>
                  <el-button type="info" :icon="Download" circle size="small" @click.stop="downloadImage(image)"/>
                  <el-button type="danger" :icon="Delete" circle size="small" @click.stop="removeImage(index)"/>
                </div>
              </div>
              <div class="image-name">{{ image.name }}</div>
            </div>
          </div>

          <!-- 上传按钮（如果未达到最大数量） -->
          <div v-if="completedFiles.length < maxCount" class="upload-placeholder">
            <el-icon class="upload-icon" size="32">
              <Plus/>
            </el-icon>
            <div class="upload-text">{{ dragText }}</div>
          </div>
        </div>
      </template>

      <!-- 列表布局：传统上传区域 -->
      <template v-else>
        <div class="upload-zone__content">
          <el-icon class="upload-zone__icon" size="48">
            <PictureFilled/>
          </el-icon>
          <div class="upload-zone__text">
            <p class="upload-zone__title">{{ dragText }}</p>
            <p class="upload-zone__subtitle">支持 {{ allowedTypes.join('、') }} 格式， 单个文件不超过 {{maxFileSize}}MB
              <template v-if="enableCompress">
                ，上传时会自动{{ compressMode === 'quality' ? '质量' : '大小' }}压缩
                <template v-if="compressMode === 'size'">至{{ maxFileSizeKb }}KB</template>
              </template>
            </p>
            <p class="upload-zone__subtitle" v-if="maxCount > 1">最多可上传 {{ maxCount }} 张图片</p>
          </div>
        </div>
      </template>

      <input ref="fileInput" type="file" :multiple="maxCount > 1" :accept="acceptTypes" @change="handleFileSelect" style="display: none"/>
    </div>

    <!-- 列表布局：统一的文件列表 -->
    <div v-if="layout === 'list'" class="unified-file-list">
      <!-- 操作栏 -->
      <div class="list-header">
        <span>图片列表 ({{ allFiles.length }} 个文件)</span>
        <div class="header-actions">
          <el-button v-if="!isUploading && hasWaitingFiles" type="primary" size="small" @click="startUpload">开始上传
          </el-button>
          <el-button v-if="isUploading" type="danger" size="small" @click="cancelUpload">取消上传</el-button>
          <el-button v-if="allFiles.length > 0" type="text" size="small" @click="clearAll">清空全部</el-button>
        </div>
      </div>

      <!-- 统一文件列表 -->
      <div v-if="allFiles.length > 0" class="file-section">
        <div class="file-list">
          <div v-for="(file, index) in allFiles" :key="file.id" class="file-item"
               :class="{ 'file-item--error': file.status === 'error' }">
            <!-- 左侧：图片预览 -->
            <div class="file-image">
              <div class="image-preview-container">
                <img v-if="file.previewUrl || file.url" :src="file.previewUrl || file.url" :alt="file.name" class="preview-image" :class="{ 'clickable': file.status === 'completed' }" @click="file.status === 'completed' ? previewImageFromList(file, index) : null"/>
                <div v-else class="image-placeholder">
                  <el-icon size="48">
                    <Picture/>
                  </el-icon>
                  <span class="placeholder-text">图片预览</span>
                </div>

                <!-- 状态覆盖层 -->
                <div v-if="file.status === 'uploading'" class="upload-overlay">
                  <el-progress :percentage="Math.round(file.progress)" :width="80" type="circle" :show-text="false"/>
                  <div class="upload-progress">{{ Math.round(file.progress) }}%</div>
                </div>
              </div>
            </div>

            <!-- 右侧：文件信息和操作 -->
            <div class="file-content">
              <!-- 文件信息 -->
              <div class="file-info">
                <div class="file-name">{{ file.name }}</div>
                <div class="file-meta">
                  <div class="meta-item">
                    <span class="meta-label">大小：</span>
                    <span class="meta-value">
                      {{ formatFileSize(file.size) }}
                      <template v-if="file.isCompressed">
                        <span class="compress-info">
                          (原始: {{ formatFileSize(file.originalSize) }}, 
                          压缩: {{ file.compressRatio }}%)
                        </span>
                      </template>
                    </span>
                  </div>
                  <div v-if="file.status !== 'completed'" class="meta-item">
                    <span class="meta-label">方式：</span>
                    <span class="meta-value">
                      {{ file.uploadMethod === 'chunk' ? '分片上传' : '普通上传' }}
                      <el-tag v-if="file.supportDirectUpload" type="success" size="small" class="direct-tag">直传</el-tag>
                    </span>
                  </div>
                  <div v-else-if="file.filePath" class="meta-item">
                    <span class="meta-label">路径：</span>
                    <span class="meta-value file-path">{{ file.filePath }}</span>
                  </div>
                </div>
              </div>

              <!-- 状态和操作 -->
              <div class="file-actions">
                <!-- 状态标签 -->
                <div class="status-section">
                  <el-tag v-if="file.status === 'waiting'" size="small" type="info">等待上传</el-tag>
                  <el-tag v-else-if="file.status === 'uploading'" size="small" type="warning">上传中</el-tag>
                  <el-tag v-else-if="file.status === 'completed'" size="small" type="success">已完成</el-tag>
                  <el-tag v-else-if="file.status === 'error'" size="small" type="danger">上传失败</el-tag>
                  <el-tag v-if="file.isCompressed" size="small" type="success" class="compressed-tag">已压缩</el-tag>
                </div>

                <!-- 操作按钮 -->
                <div class="action-buttons">
                  <template v-if="file.status === 'completed'">
                    <el-button type="primary" size="small" @click="previewImageFromList(file, index)">
                      <el-icon><View/></el-icon>预览
                    </el-button>
                    <el-button type="info" size="small" @click="copyPath(file.filePath)">
                      <el-icon><CopyDocument/></el-icon>复制路径
                    </el-button>
                    <el-button type="success" size="small" @click="downloadImage(file)">
                      <el-icon><Download/></el-icon>下载
                    </el-button>
                  </template>
                  <template v-else-if="file.status === 'error'">
                    <el-button type="warning" size="small" @click="retryUpload(file)">
                      <el-icon><RefreshRight/></el-icon>重试
                    </el-button>
                  </template>

                  <el-button v-if="file.status !== 'uploading'" type="danger" size="small" @click="removeFileFromList(file, index)" :disabled="isUploading && file.status !== 'error'">
                    <el-icon><Delete/></el-icon>删除
                  </el-button>
                </div>
              </div>

              <!-- 错误信息 -->
              <div v-if="file.status === 'error' && file.errorMessage" class="error-message">
                <el-alert :title="file.errorMessage" type="error" size="small" :closable="false" show-icon/>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>

    <!-- 图片预览对话框 -->
    <el-dialog v-model="previewVisible" title="图片预览" width="80%" :before-close="handlePreviewClose" append-to-body>
      <div class="image-preview-dialog">
        <div class="preview-toolbar">
          <div class="toolbar-left">
            <span class="image-info">
              {{ currentPreviewImage?.name }} 
              ({{ currentPreviewIndex + 1 }}/{{ completedFiles.length }})
            </span>
          </div>
          <div class="toolbar-right">
            <el-button-group>
              <el-button :icon="ZoomOut" @click="zoomOut" :disabled="scale <= 0.2"/>
              <el-button @click="resetZoom">{{ Math.round(scale * 100) }}%</el-button>
              <el-button :icon="ZoomIn" @click="zoomIn" :disabled="scale >= 3"/>
            </el-button-group>
            <el-button :icon="RefreshLeft" @click="rotateLeft"/>
            <el-button :icon="RefreshRight" @click="rotateRight"/>
            <el-button :icon="Download" @click="downloadCurrentImage"/>
          </div>
        </div>

        <div class="preview-container" ref="previewContainer">
          <img v-if="currentPreviewImage" :src="currentPreviewImage.previewUrl || currentPreviewImage.url" :alt="currentPreviewImage.name" class="preview-image"
               :style="{
              transform: `scale(${scale}) rotate(${rotation}deg)`,
              maxWidth: '100%',
              maxHeight: '100%'
            }" @wheel="handleWheel"/>
        </div>

        <!-- 缩略图导航 -->
        <div v-if="completedFiles.length > 1" class="preview-nav">
          <div class="nav-thumbnails">
            <div v-for="(image, index) in completedFiles" :key="image.id" class="nav-thumbnail" :class="{ active: index === currentPreviewIndex }" @click="switchPreviewImage(index)">
              <img :src="image.previewUrl || image.url" :alt="image.name"/>
            </div>
          </div>
        </div>
      </div>

      <template #footer>
        <div class="dialog-footer">
          <el-button v-if="completedFiles.length > 1" @click="prevImage" :disabled="currentPreviewIndex === 0">上一张
          </el-button>
          <el-button @click="previewVisible = false">关闭</el-button>
          <el-button v-if="completedFiles.length > 1" @click="nextImage"
                     :disabled="currentPreviewIndex === completedFiles.length - 1">下一张
          </el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import {computed, nextTick, onMounted, ref, watch} from 'vue'
import {ElMessage} from 'element-plus'
import {
  CopyDocument,
  Delete,
  Download,
  Picture,
  PictureFilled,
  Plus,
  RefreshLeft,
  RefreshRight,
  View,
  ZoomIn,
  ZoomOut
} from '@element-plus/icons-vue'
import {createUploadManager, formatFileSize, generateFileId, generatePreviewUrl} from '@/utils/upload-utils'

// Props
const props = defineProps({
  // 最大图片数量
  maxCount: {
    type: Number,
    default: 5
  },
  // 单个文件最大大小(MB)
  maxFileSize: {
    type: Number,
    default: 10
  },
  // 允许的图片类型
  allowedTypes: {
    type: Array,
    default: () => ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp']
  },
  // 布局方式: 'list' | 'grid'
  layout: {
    type: String,
    default: 'grid',
    validator: (value) => ['list', 'grid'].includes(value)
  },
  // 默认存储配置ID
  defaultConfigId: {
    type: Number,
    default: null
  },
  // 默认上传目录
  defaultDir: {
    type: String,
    default: 'images'
  },
  // 是否禁用
  disabled: {
    type: Boolean,
    default: false
  },
  // 分片大小(MB)
  chunkSize: {
    type: Number,
    default: 5
  },
  // 预设图片列表 - 支持数组或字符串（逗号分隔）
  modelValue: {
    type: [Array, String],
    default: () => []
  },
  // 是否自动开始上传
  autoUpload: {
    type: Boolean,
    default: true
  },
  // 是否启用图片压缩
  enableCompress: {
    type: Boolean,
    default: false
  },
  // 压缩模式: 'quality'(质量压缩) | 'size'(大小压缩)
  compressMode: {
    type: String,
    default: 'quality',
    validator: (value) => ['quality', 'size'].includes(value)
  },
  // 压缩质量 (0-1)
  compressQuality: {
    type: Number,
    default: 0.5,
    validator: (value) => value >= 0.1 && value <= 1
  },
  // 目标文件大小（KB），仅在size模式下使用
  maxFileSizeKb: {
    type: Number,
    default: 100,
    validator: (value) => value >= 10 && value <= 2048
  },
  // 压缩后最小文件大小限制（KB），小于此值不进行压缩
  minCompressSize: {
    type: Number,
    default: 50
  }
})

// Emits
const emit = defineEmits(['update:modelValue', 'upload-success', 'upload-error', 'upload-progress', 'preview', 'remove', 'compress-start', 'compress-end'])

// 图片压缩工具函数
function compressImage(file, options = {}) {
  return new Promise((resolve, reject) => {
    const {
      mode = props.compressMode,
      quality = props.compressQuality,
      targetSizeKb = props.maxFileSizeKb,
      minSize = props.minCompressSize * 1024 // 转换为字节
    } = options

    // 如果文件小于最小压缩大小，直接返回原文件
    if (file.size < minSize) {
      resolve(file)
      return
    }

    // 根据模式选择压缩方式
    if (mode === 'quality') {
      compressImageByQuality(file, quality, resolve, reject)
    } else if (mode === 'size') {
      compressImageBySize(file, targetSizeKb, resolve, reject)
    } else {
      reject(new Error('不支持的压缩模式'))
    }
  })
}

// 质量压缩模式
function compressImageByQuality(file, quality, resolve, reject) {
  const img = new Image()
  const canvas = document.createElement('canvas')
  const ctx = canvas.getContext('2d')

  img.onload = () => {
    try {
      // 保持原始尺寸
      canvas.width = img.width
      canvas.height = img.height

      // 启用图像平滑以保证清晰度
      ctx.imageSmoothingEnabled = true
      ctx.imageSmoothingQuality = 'high'

      // 填充白色背景（避免透明图片变黑，JPEG不支持透明）
      ctx.fillStyle = '#FFFFFF'
      ctx.fillRect(0, 0, canvas.width, canvas.height)

      // 绘制图片
      ctx.drawImage(img, 0, 0)

      // 转换为Blob，强制使用JPEG格式
      canvas.toBlob((blob) => {
        if (blob) {
          // 如果压缩后文件反而更大，返回原文件
          if (blob.size >= file.size * 0.9) {
            resolve(file)
            return
          }

          // 将文件名扩展名改为.jpg
          const newFileName = file.name.replace(/\.[^.]+$/, '.jpg')

          // 创建新的File对象，强制使用JPEG格式
          const compressedFile = new File([blob], newFileName, {
            type: 'image/jpeg',
            lastModified: Date.now()
          })

          // 添加压缩信息
          compressedFile.originalSize = file.size
          compressedFile.compressRatio = ((file.size - blob.size) / file.size * 100).toFixed(1)
          compressedFile.isCompressed = true

          // 清理资源
          URL.revokeObjectURL(img.src)

          resolve(compressedFile)
        } else {
          reject(new Error('图片压缩失败'))
        }
      }, 'image/jpeg', quality)
    } catch (error) {
      // 清理资源
      URL.revokeObjectURL(img.src)
      reject(error)
    }
  }

  img.onerror = () => {
    URL.revokeObjectURL(img.src)
    reject(new Error('图片加载失败'))
  }

  // 加载图片
  img.src = URL.createObjectURL(file)
}

// 大小压缩模式
function compressImageBySize(file, targetSizeKb, resolve, reject) {
  const targetSizeBytes = targetSizeKb * 1024
  const img = new Image()
  
  img.onload = () => {
    try {
      // 计算合适的初始尺寸缩放比例
      const originalPixels = img.width * img.height
      const compressionRatio = file.size / targetSizeBytes
      
      // 根据目标大小估算需要的尺寸缩放
      let scaleFactor = 1
      if (compressionRatio > 4) {
        scaleFactor = Math.sqrt(1 / (compressionRatio * 0.3)) // 更激进的缩放
      } else if (compressionRatio > 2) {
        scaleFactor = Math.sqrt(1 / (compressionRatio * 0.5))
      }
      
      scaleFactor = Math.max(0.3, Math.min(1, scaleFactor)) // 限制在0.3-1之间
      
      const canvas = document.createElement('canvas')
      const ctx = canvas.getContext('2d')
      
      // 设置压缩后的尺寸
      canvas.width = Math.round(img.width * scaleFactor)
      canvas.height = Math.round(img.height * scaleFactor)

      // 启用图像平滑以保证清晰度
      ctx.imageSmoothingEnabled = true
      ctx.imageSmoothingQuality = 'high'

      // 填充白色背景（避免透明图片变黑，JPEG不支持透明）
      ctx.fillStyle = '#FFFFFF'
      ctx.fillRect(0, 0, canvas.width, canvas.height)

      // 绘制压缩后的图片
      ctx.drawImage(img, 0, 0, canvas.width, canvas.height)

      // 将文件名扩展名改为.jpg
      const newFileName = file.name.replace(/\.[^.]+$/, '.jpg')

      // 循环压缩直到达到目标大小
      let currentQuality = 0.8
      let attempts = 0
      const maxAttempts = 15

      function tryCompress() {
        canvas.toBlob((blob) => {
          if (blob) {
            console.log(`压缩尝试 ${attempts + 1}: 当前大小 ${(blob.size / 1024).toFixed(1)}KB, 目标 ${targetSizeKb}KB, 质量 ${(currentQuality * 100).toFixed(0)}%`)
            
            // 如果达到目标大小
            if (blob.size <= targetSizeBytes) {
              // 创建新的File对象，强制使用JPEG格式
              const compressedFile = new File([blob], newFileName, {
                type: 'image/jpeg',
                lastModified: Date.now()
              })

              // 添加压缩信息
              compressedFile.originalSize = file.size
              compressedFile.compressRatio = ((file.size - blob.size) / file.size * 100).toFixed(1)
              compressedFile.isCompressed = true

              console.log(`压缩成功: ${file.name}, 原始 ${(file.size / 1024).toFixed(1)}KB → ${(blob.size / 1024).toFixed(1)}KB`)

              // 清理资源
              URL.revokeObjectURL(img.src)

              resolve(compressedFile)
            } 
            // 如果还没达到目标大小但已达到最大尝试次数或最低质量
            else if (attempts >= maxAttempts || currentQuality <= 0.05) {
              console.log(`压缩达到极限: 尝试次数 ${attempts}, 最终大小 ${(blob.size / 1024).toFixed(1)}KB`)
              
              // 即使没达到目标，也返回压缩后的文件，强制使用JPEG格式
              const compressedFile = new File([blob], newFileName, {
                type: 'image/jpeg',
                lastModified: Date.now()
              })

              compressedFile.originalSize = file.size
              compressedFile.compressRatio = ((file.size - blob.size) / file.size * 100).toFixed(1)
              compressedFile.isCompressed = true

              // 清理资源
              URL.revokeObjectURL(img.src)

              resolve(compressedFile)
            } else {
              // 继续压缩，更激进地降低质量
              attempts++
              
              // 根据当前大小与目标大小的比例调整质量下降幅度
              const sizeRatio = blob.size / targetSizeBytes
              let qualityReduction
              
              if (sizeRatio > 3) {
                qualityReduction = 0.15 // 大幅降低质量
              } else if (sizeRatio > 2) {
                qualityReduction = 0.1
              } else {
                qualityReduction = 0.05
              }
              
              currentQuality = Math.max(0.05, currentQuality - qualityReduction)
              
              // 短暂延时后继续
              setTimeout(tryCompress, 10)
            }
          } else {
            reject(new Error('图片压缩失败'))
          }
        }, 'image/jpeg', currentQuality)
      }

      // 开始压缩
      tryCompress()
    } catch (error) {
      // 清理资源
      URL.revokeObjectURL(img.src)
      reject(error)
    }
  }

  img.onerror = () => {
    URL.revokeObjectURL(img.src)
    reject(new Error('图片加载失败'))
  }

  // 加载图片
  img.src = URL.createObjectURL(file)
}


// 响应式数据
const dropZone = ref(null)
const fileInput = ref(null)
const previewContainer = ref(null)
const isDragOver = ref(false)
const isUploading = ref(false)
// 数据格式转换工具函数
function normalizeModelValue(value) {
  if (!value) return []
  
  // 如果已经是数组，直接返回
  if (Array.isArray(value)) {
    return value.map(img => {
      if (typeof img === 'string') {
        // 如果数组元素是字符串，转换为对象
        const fileName = img.split('/').pop() || '图片'
        return {
          id: generateFileId('image'),
          name: fileName,
          url: img,
          filePath: img, // 保持原值，可能是相对路径或完整URL
          previewUrl: img
        }
      }
      return {
        ...img,
        url: img.url || img.filePath,
        previewUrl: img.previewUrl || img.url || img.filePath
      }
    })
  }
  
  // 如果是字符串，按逗号分割
  if (typeof value === 'string') {
    return value.split(',').filter(url => url.trim()).map(url => {
      const trimmedUrl = url.trim()
      const fileName = trimmedUrl.split('/').pop() || '图片'
      return {
        id: generateFileId('image'),
        name: fileName,
        url: trimmedUrl,
        filePath: trimmedUrl, // 保持原值，可能是相对路径或完整URL
        previewUrl: trimmedUrl
      }
    })
  }
  
  return []
}

// 数据格式转换为输出格式
function formatOutputValue(files) {
  const completedFiles = files.filter(file => file.status === 'completed')
  
  // 如果原始输入是字符串，输出也是字符串
  if (typeof props.modelValue === 'string') {
    return completedFiles.map(file => file.url || file.filePath).join(',')
  }
  
  // 否则输出数组格式
  return completedFiles.map(file => ({
    id: file.id,
    name: file.name,
    size: file.size,
    url: file.url || file.filePath,
    filePath: file.filePath,
    previewUrl: file.previewUrl || file.url || file.filePath
  }))
}

// 统一的文件列表，包含所有状态的文件
const allFiles = ref([...normalizeModelValue(props.modelValue).map(img => ({
  id: img.id || generateFileId('image'),
  name: img.name,
  size: img.size || 0,
  filePath: img.filePath,
  url: img.url,
  previewUrl: img.previewUrl || img.url,
  status: 'completed'
}))])
const storageConfigs = ref([])
const selectedConfigId = ref(props.defaultConfigId)
const uploadDir = ref(props.defaultDir)
// 动态文件大小限制（来自存储配置）
const dynamicMaxFileSize = ref(props.maxFileSize)

// 预览相关
const previewVisible = ref(false)
const currentPreviewImage = ref(null)
const currentPreviewIndex = ref(0)
const scale = ref(1)
const rotation = ref(0)

// 计算属性
const acceptTypes = computed(() => {
  return props.allowedTypes.map(type => `.${type}`).join(',')
})

const dragText = computed(() => {
  if (props.disabled) return '上传已禁用'
  if (isUploading.value) return '上传中...'
  if (props.layout === 'grid' && completedFiles.value.length >= props.maxCount) {
    return '已达到最大数量'
  }
  return '点击或拖拽上传图片'
})

const hasWaitingFiles = computed(() => {
  return allFiles.value.some(file => file.status === 'waiting')
})

// 已完成的文件（用于网格模式显示和数量限制）
const completedFiles = computed(() => {
  return allFiles.value.filter(file => file.status === 'completed')
})

// 处理文件选择
async function handleFileSelect(event) {
  const files = Array.from(event.target.files)
  await addFilesToQueue(files)
  // 清空input
  event.target.value = ''
}

// 创建上传管理器（延迟初始化，避免循环依赖）
let uploadManager = null

function getUploadManager() {
  if (!uploadManager) {
    uploadManager = createUploadManager({
      allowedTypes: props.allowedTypes,
      maxFileSize: dynamicMaxFileSize.value,
      maxCount: props.maxCount,
      chunkSize: props.chunkSize,
      autoUpload: props.autoUpload,
      currentCount: () => completedFiles.value.length,
      queueCount: () => allFiles.value.filter(f => f.status !== 'completed').length,
      disabled: () => props.disabled,
      isUploading: () => isUploading.value,
      canAddMore: () => completedFiles.value.length < props.maxCount,
      onDragOver: (isDragOver) => {
        isDragOver.value = isDragOver
      },
      onDragLeave: (isDragOver) => {
        isDragOver.value = isDragOver
      },
      onDrop: (files) => addFilesToQueue(files)
    })
  }
  return uploadManager
}

// 拖拽处理器
function handleDragOver(event) {
  event.preventDefault()
  if (!props.disabled && !isUploading.value && completedFiles.value.length < props.maxCount) {
    isDragOver.value = true
  }
}

function handleDragLeave(event) {
  event.preventDefault()
  isDragOver.value = false
}

async function handleDrop(event) {
  event.preventDefault()
  isDragOver.value = false

  if (props.disabled || isUploading.value || completedFiles.value.length >= props.maxCount) return

  const files = Array.from(event.dataTransfer.files)
  await addFilesToQueue(files)
}

// 点击上传区域
function handleClickUpload() {
  if (props.disabled || isUploading.value || completedFiles.value.length >= props.maxCount) return
  fileInput.value.click()
}

// 添加文件到队列
async function addFilesToQueue(files) {
  const {
    validFiles,
    errors
  } = getUploadManager().validator.validateFiles(files, allFiles.value.filter(f => f.status !== 'completed'))

  // 显示错误信息
  errors.forEach(error => ElMessage.error(error))

  // 处理有效文件
  const processedFiles = []
  for (const file of validFiles) {
    let processedFile = file
    let originalSize = file.size
    let compressRatio = 0
    let isCompressed = false

    // 如果启用压缩且是图片文件
    if (props.enableCompress && file.type.startsWith('image/')) {
      try {
        // 发出压缩开始事件
        emit('compress-start', { file: file })

        // 显示压缩提示
        const compressTip = props.compressMode === 'quality' ? 
          `正在质量压缩图片 ${file.name}...` : 
          `正在压缩图片 ${file.name} 至 ${props.maxFileSizeKb}KB...`
        
        const loadingMessage = ElMessage({
          message: compressTip,
          type: 'info',
          duration: 0,
          showClose: false
        })

        // 执行压缩
        processedFile = await compressImage(file)
        
        // 关闭加载提示
        loadingMessage.close()

        // 检查是否真的压缩了
        if (processedFile.isCompressed) {
          originalSize = processedFile.originalSize
          compressRatio = processedFile.compressRatio
          isCompressed = true

          // 发出压缩完成事件
          emit('compress-end', { 
            originalFile: file,
            compressedFile: processedFile,
            originalSize,
            newSize: processedFile.size,
            compressRatio
          })

          if (props.compressMode === 'size') {
            const finalSizeKB = (processedFile.size / 1024).toFixed(1)
            const targetKB = props.maxFileSizeKb
            if (processedFile.size <= props.maxFileSizeKb * 1024) {
              ElMessage.success(`图片压缩完成，压缩率: ${compressRatio}%，最终大小: ${finalSizeKB}KB`)
            } else {
              ElMessage.warning(`图片已尽力压缩，压缩率: ${compressRatio}%，最终大小: ${finalSizeKB}KB (目标: ${targetKB}KB)`)
            }
          } else {
            ElMessage.success(`图片压缩完成，压缩率: ${compressRatio}%`)
          }
        } else {
          ElMessage.info(`图片 ${file.name} 无需压缩`)
        }
      } catch (error) {
        console.error('图片压缩失败:', error)
        ElMessage.warning(`图片 ${file.name} 压缩失败，将使用原图`)
        processedFile = file // 使用原文件
      }
    }

    // 生成预览URL
    const previewUrl = await generatePreviewUrl(processedFile)

    const fileObj = {
      id: generateFileId('image'),
      file: processedFile,
      name: processedFile.name,
      size: processedFile.size,
      type: processedFile.type,
      status: 'waiting',
      progress: 0,
      uploadMethod: getUploadManager().determineUploadMethod(processedFile),
      supportDirectUpload: false,
      errorMessage: '',
      filePath: '',
      uploadId: '',
      etags: [],
      previewUrl: previewUrl,
      // 压缩相关信息
      originalSize: originalSize,
      compressRatio: compressRatio,
      isCompressed: isCompressed
    }

    processedFiles.push(fileObj)
  }

  allFiles.value.push(...processedFiles)

  // 如果自动上传，立即开始上传
  if (props.autoUpload && processedFiles.length > 0) {
    nextTick(() => {
      startUpload()
    })
  }
}

// 移除文件（通过索引）
function removeFile(index) {
  allFiles.value.splice(index, 1)
}

// 移除图片（通过索引，用于网格模式）
function removeImage(index) {
  const completedFileIndex = allFiles.value.findIndex((file, i) => file.status === 'completed' && completedFiles.value.indexOf(file) === index)
  if (completedFileIndex !== -1) {
    allFiles.value.splice(completedFileIndex, 1)
  }
  emit('remove', {index})
}

// 开始上传
async function startUpload() {
  // 确保存储配置已加载
  if (storageConfigs.value.length === 0) {
    try {
      await loadStorageConfigs()
    } catch (error) {
      ElMessage.error('加载存储配置失败，请检查网络连接')
      return
    }
  }

  if (!selectedConfigId.value) {
    if (storageConfigs.value.length > 0) {
      // 使用便捷方法获取默认配置ID
      const {getDefaultConfigId} = await import('@/store/modules/fileConfig')
      selectedConfigId.value = await getDefaultConfigId(storageConfigs.value)
    } else {
      ElMessage.error('没有可用的存储配置，请先在系统管理中配置存储')
      return
    }
  }

  const waitingFiles = allFiles.value.filter(file => file.status === 'waiting')
  if (waitingFiles.length === 0) {
    ElMessage.warning('没有文件需要上传')
    return
  }

  isUploading.value = true

  try {
    const config = storageConfigs.value.find(c => c.configId === selectedConfigId.value)

    for (const fileObj of waitingFiles) {
      try {
        fileObj.status = 'uploading'
        fileObj.progress = 0
        fileObj.errorMessage = ''

        const onProgress = (progress) => {
          emit('upload-progress', {file: fileObj, progress})
        }

        if (fileObj.uploadMethod === 'chunk') {
          // 将MB转换为字节
          const chunkSizeBytes = props.chunkSize * 1024 * 1024
          await getUploadManager().uploadFileWithChunks(
              fileObj, config, selectedConfigId.value, uploadDir.value, chunkSizeBytes, onProgress
          )
        } else {
          await getUploadManager().uploadFileNormally(
              fileObj, config, selectedConfigId.value, uploadDir.value, onProgress
          )
        }

        fileObj.status = 'completed'
        fileObj.progress = 100

        // 使用后端返回的URL，如果没有则尝试获取
        let url = fileObj.url
        if (!url) {
          url = await getUploadManager().getImageUrl(fileObj.filePath, selectedConfigId.value)
          fileObj.url = url
        }

        // 更新文件对象的完整信息
        fileObj.filePath = fileObj.filePath
        fileObj.url = url

        emit('upload-success', {
          file: fileObj,
          image: fileObj
        })

      } catch (error) {
        fileObj.status = 'error'
        fileObj.errorMessage = error.message || '上传失败'

        emit('upload-error', {
          file: fileObj,
          error: error
        })
      }
    }

    ElMessage.success('上传完成')

  } catch (error) {
    ElMessage.error('上传过程中发生错误：' + error.message)
  } finally {
    isUploading.value = false
  }
}

// 重试上传
function retryUpload(fileObj) {
  const fileIndex = allFiles.value.findIndex(f => f.id === fileObj.id)
  if (fileIndex !== -1) {
    allFiles.value[fileIndex].status = 'waiting'
    allFiles.value[fileIndex].progress = 0
    allFiles.value[fileIndex].errorMessage = ''
  }
}

// 取消上传
async function cancelUpload() {
  try {
    await ElMessageBox.confirm('确定要取消上传吗？', '提示', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    })

    isUploading.value = false

    // 重置所有上传中的文件状态
    allFiles.value.forEach(file => {
      if (file.status === 'uploading') {
        file.status = 'waiting'
        file.progress = 0
      }
    })

    ElMessage.info('已取消上传')
  } catch (error) {
    // 用户取消确认
  }
}

// 清空全部
function clearAll() {
  allFiles.value = []
}

// 从统一列表中预览图片
function previewImageFromList(file, listIndex) {
  if (file.status === 'completed') {
    const completedIndex = completedFiles.value.findIndex(img => img.id === file.id)
    if (completedIndex !== -1) {
      previewImage(file, completedIndex)
    }
  }
}

// 从统一列表中删除文件
function removeFileFromList(file, listIndex) {
  const fileIndex = allFiles.value.findIndex(f => f.id === file.id)
  if (fileIndex !== -1) {
    allFiles.value.splice(fileIndex, 1)
    emit('remove', {index: fileIndex})
  }
}

// 复制路径
function copyPath(path) {
  getUploadManager().copyPath(path)
}

// 下载图片
async function downloadImage(image) {
  try {
    const link = document.createElement('a')
    link.href = image.url || image.filePath
    link.download = image.name
    document.body.appendChild(link)
    link.click()
    document.body.removeChild(link)
  } catch (error) {
    ElMessage.error('下载失败: ' + error.message)
  }
}

// 预览图片
function previewImage(image, index) {
  currentPreviewImage.value = image
  currentPreviewIndex.value = index
  previewVisible.value = true
  resetZoom()
  emit('preview', {image, index})
}

// 关闭预览
function handlePreviewClose() {
  previewVisible.value = false
  currentPreviewImage.value = null
  currentPreviewIndex.value = 0
  resetZoom()
}

// 缩放控制
function zoomIn() {
  if (scale.value < 3) scale.value += 0.2
}

function zoomOut() {
  if (scale.value > 0.2) scale.value -= 0.2
}

function resetZoom() {
  scale.value = 1
  rotation.value = 0
}

// 旋转控制
function rotateLeft() {
  rotation.value -= 90
}

function rotateRight() {
  rotation.value += 90
}

// 鼠标滚轮缩放
function handleWheel(event) {
  event.preventDefault()
  if (event.deltaY < 0) {
    zoomIn()
  } else {
    zoomOut()
  }
}

// 切换图片
function prevImage() {
  if (currentPreviewIndex.value > 0) {
    switchPreviewImage(currentPreviewIndex.value - 1)
  }
}

function nextImage() {
  if (currentPreviewIndex.value < completedFiles.value.length - 1) {
    switchPreviewImage(currentPreviewIndex.value + 1)
  }
}

function switchPreviewImage(index) {
  if (index >= 0 && index < completedFiles.value.length) {
    currentPreviewIndex.value = index
    currentPreviewImage.value = completedFiles.value[index]
    resetZoom()
  }
}

// 下载当前预览图片
function downloadCurrentImage() {
  if (currentPreviewImage.value) {
    downloadImage(currentPreviewImage.value)
  }
}

// 加载存储配置
async function loadStorageConfigs() {
  try {
    storageConfigs.value = await getUploadManager().loadStorageConfigs()

    if (!selectedConfigId.value && storageConfigs.value.length > 0) {
      // 使用便捷方法获取默认配置ID
      const {getDefaultConfigId} = await import('@/store/modules/fileConfig')
      selectedConfigId.value = await getDefaultConfigId(storageConfigs.value)
    }

    // 更新动态文件大小限制
    updateDynamicMaxFileSize()
  } catch (error) {
    console.error('加载存储配置失败:', error)
  }
}

// 更新动态文件大小限制
function updateDynamicMaxFileSize() {
  if (selectedConfigId.value && storageConfigs.value.length > 0) {
    const config = storageConfigs.value.find(c => c.configId === selectedConfigId.value)
    if (config && config.maxFileSize) {
      // 将字节转换为MB
      dynamicMaxFileSize.value = Math.floor(config.maxFileSize / (1024 * 1024))
    }
  }
  // 重置上传管理器以使用新的文件大小限制
  uploadManager = null
}

// 防止递归更新的标志
const isInternalUpdate = ref(false)

// 监听外部属性变化
watch(() => props.modelValue, (newVal) => {
  // 如果是内部更新触发的，跳过
  if (isInternalUpdate.value) {
    return
  }
  
  const normalizedFiles = normalizeModelValue(newVal)
  const newCompletedFiles = normalizedFiles.map(img => ({
    id: img.id || generateFileId('image'),
    name: img.name,
    size: img.size || 0,
    filePath: img.filePath,
    url: img.url,
    previewUrl: img.previewUrl || img.url,
    status: 'completed'
  }))

  // 保留非completed状态的文件，替换completed状态的文件
  const nonCompletedFiles = allFiles.value.filter(file => file.status !== 'completed')
  allFiles.value = [...nonCompletedFiles, ...newCompletedFiles]
}, {immediate: true, deep: true})

// 监听完成文件变化，实时更新 modelValue
watch(completedFiles, (newCompletedFiles) => {
  // 设置内部更新标志
  isInternalUpdate.value = true
  
  const outputValue = formatOutputValue(allFiles.value)
  emit('update:modelValue', outputValue)
  
  // 在下一个 tick 中重置标志
  nextTick(() => {
    isInternalUpdate.value = false
  })
}, {deep: true})

watch(() => props.defaultConfigId, (newVal) => {
  if (newVal && newVal !== selectedConfigId.value) {
    selectedConfigId.value = newVal
    updateDynamicMaxFileSize()
  }
}, {immediate: false})

watch(() => props.defaultDir, (newVal) => {
  uploadDir.value = newVal
})

// 监听选中的配置ID变化
watch(selectedConfigId, () => {
  updateDynamicMaxFileSize()
})

// 组件挂载
onMounted(() => {
  // 总是加载存储配置，确保组件可用
  nextTick(() => {
    loadStorageConfigs()
  })
})
</script>

<style scoped lang="scss">
.image-upload {
  .upload-zone {
    border: 2px dashed #dcdfe6;
    border-radius: 6px;
    padding: 20px;
    text-align: center;
    cursor: pointer;
    transition: all 0.3s ease;
    background-color: #fafafa;

    &:hover:not(.upload-zone--disabled) {
      border-color: #409eff;
      background-color: #f0f9ff;
    }

    &--dragover {
      border-color: #409eff;
      background-color: #f0f9ff;
    }

    &--disabled {
      cursor: not-allowed;
      opacity: 0.6;
    }

    &--grid {
      padding: 0;
    }

    &__content {
      display: flex;
      flex-direction: column;
      align-items: center;
    }

    &__icon {
      color: #c0c4cc;
      margin-bottom: 16px;
    }

    &__title {
      font-size: 16px;
      color: #303133;
      margin: 0 0 8px 0;
    }

    &__subtitle {
      font-size: 14px;
      color: #909399;
      margin: 4px 0;
    }
  }

  // 网格布局
  .image-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
    gap: 12px;
    padding: 12px;

    .image-item {
      position: relative;

      .image-wrapper {
        position: relative;
        width: 100%;
        height: 120px;
        border-radius: 6px;
        overflow: hidden;
        border: 1px solid #dcdfe6;

        .image-preview {
          width: 100%;
          height: 100%;
          object-fit: cover;
          cursor: pointer;
        }

        .image-overlay {
          position: absolute;
          top: 0;
          left: 0;
          right: 0;
          bottom: 0;
          background: rgba(0, 0, 0, 0.5);
          display: flex;
          align-items: center;
          justify-content: center;
          opacity: 0;
          transition: opacity 0.3s ease;

          .image-actions {
            display: flex;
            gap: 8px;
          }
        }

        &:hover .image-overlay {
          opacity: 1;
        }

        .image-name {
          position: absolute;
          bottom: 0;
          left: 0;
          right: 0;
          background: rgba(0, 0, 0, 0.7);
          color: white;
          padding: 4px;
          font-size: 12px;
          text-align: center;
          white-space: nowrap;
          overflow: hidden;
          text-overflow: ellipsis;
        }
      }
    }

    .upload-placeholder {
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      height: 120px;
      border: 2px dashed #dcdfe6;
      border-radius: 6px;
      background-color: #fafafa;
      transition: all 0.3s ease;

      &:hover {
        border-color: #409eff;
        background-color: #f0f9ff;
      }

      .upload-icon {
        color: #c0c4cc;
        margin-bottom: 8px;
      }

      .upload-text {
        font-size: 12px;
        color: #909399;
      }
    }
  }

  // 列表布局
  .upload-queue,
  .uploaded-images {
    margin-top: 20px;

    .queue-header,
    .images-header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 12px;
      background-color: #f5f7fa;
      border-radius: 4px 4px 0 0;
      border: 1px solid #ebeef5;
      font-weight: 500;
    }

    .file-list,
    .images-list {
      border: 1px solid #ebeef5;
      border-top: none;
      border-radius: 0 0 4px 4px;
    }

    .file-item,
    .image-item-list {
      display: flex;
      align-items: center;
      padding: 12px;
      border-bottom: 1px solid #ebeef5;

      &:last-child {
        border-bottom: none;
      }

      &.file-item--error {
        background-color: #fef0f0;
      }

      .image-thumbnail {
        width: 40px;
        height: 40px;
        border-radius: 4px;
        overflow: hidden;
        border: 1px solid #dcdfe6;
        margin-right: 12px;

        .thumbnail-img {
          width: 100%;
          height: 100%;
          object-fit: cover;
          cursor: pointer;
        }

        .thumbnail-placeholder {
          width: 100%;
          height: 100%;
          display: flex;
          align-items: center;
          justify-content: center;
          background-color: #f5f7fa;
          color: #c0c4cc;
        }
      }

      .file-info,
      .image-details {
        flex: 1;

        .file-name,
        .image-name {
          font-weight: 500;
          color: #303133;
          margin-bottom: 4px;
        }

        .file-meta,
        .image-path,
        .image-size {
          font-size: 12px;
          color: #909399;

          .direct-upload-tag {
            color: #67c23a;
            font-weight: 500;
          }
        }

        .image-path {
          word-break: break-all;
          margin-bottom: 2px;
        }
      }

      .file-actions,
      .image-actions {
        display: flex;
        align-items: center;
        gap: 12px;

        .file-status {
          display: flex;
          align-items: center;
          gap: 8px;

          .progress-text {
            font-size: 12px;
            color: #909399;
          }
        }
      }

      .file-error {
        width: 100%;
        margin-top: 8px;
      }
    }
  }

  // 统一文件列表样式
  .unified-file-list {
    margin-top: 16px;

    .list-header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 12px 16px;
      background-color: #f5f7fa;
      border-radius: 6px 6px 0 0;
      border: 1px solid #e4e7ed;
      font-weight: 500;
      color: #303133;

      .header-actions {
        display: flex;
        gap: 8px;
      }
    }

    .file-section {
      border: 1px solid #e4e7ed;
      border-top: none;

      &:last-child {
        border-radius: 0 0 6px 6px;
      }

      .section-title {
        padding: 8px 16px;
        background-color: #fafafa;
        border-bottom: 1px solid #e4e7ed;
        font-size: 13px;
        font-weight: 500;
        color: #606266;
      }

      .file-list {
        .file-item {
          display: flex;
          border-bottom: 1px solid #f0f0f0;
          padding: 16px;
          gap: 16px;
          align-items: flex-start;

          &:last-child {
            border-bottom: none;
          }

          &.file-item--error {
            background-color: #fef0f0;
          }

          // 左侧图片区域
          .file-image {
            flex-shrink: 0;

            .image-preview-container {
              position: relative;
              width: 120px;
              height: 120px;
              border-radius: 8px;
              overflow: hidden;
              border: 1px solid #e4e7ed;
              background-color: #f8f9fa;

              .preview-image {
                width: 100%;
                height: 100%;
                object-fit: cover;
                display: block;

                &.clickable {
                  cursor: pointer;
                  transition: transform 0.2s ease;

                  &:hover {
                    transform: scale(1.05);
                  }
                }
              }

              .image-placeholder {
                width: 100%;
                height: 100%;
                display: flex;
                flex-direction: column;
                align-items: center;
                justify-content: center;
                color: #c0c4cc;

                .placeholder-text {
                  font-size: 12px;
                  margin-top: 8px;
                }
              }

              .upload-overlay {
                position: absolute;
                top: 0;
                left: 0;
                right: 0;
                bottom: 0;
                background-color: rgba(0, 0, 0, 0.6);
                display: flex;
                flex-direction: column;
                align-items: center;
                justify-content: center;
                color: white;

                .upload-progress {
                  margin-top: 12px;
                  font-size: 14px;
                  font-weight: 500;
                }
              }
            }
          }

          // 右侧内容区域
          .file-content {
            flex: 1;
            display: flex;
            flex-direction: column;
            min-height: 120px;

            .file-info {
              flex: 1;
              margin-bottom: 12px;

              .file-name {
                font-size: 16px;
                font-weight: 500;
                color: #303133;
                margin-bottom: 8px;
                line-height: 1.4;
                word-break: break-word;
              }

              .file-meta {
                .meta-item {
                  display: flex;
                  align-items: center;
                  margin-bottom: 4px;
                  font-size: 13px;

                  .meta-label {
                    color: #909399;
                    min-width: 40px;
                    flex-shrink: 0;
                  }

                  .meta-value {
                    color: #606266;

                    &.file-path {
                      font-family: monospace;
                      word-break: break-all;
                    }
                  }

                  .direct-tag {
                    margin-left: 8px;
                  }

                  .compress-info {
                    color: #67c23a;
                    font-size: 12px;
                    font-weight: 500;
                    margin-left: 4px;
                  }
                }
              }
            }

            .file-actions {
              display: flex;
              justify-content: space-between;
              align-items: center;
              margin-top: auto;

              .status-section {
                flex-shrink: 0;
                display: flex;
                gap: 4px;
                align-items: center;

                .compressed-tag {
                  margin-left: 4px;
                }
              }

              .action-buttons {
                display: flex;
                gap: 8px;
                flex-wrap: wrap;
              }
            }

            .error-message {
              margin-top: 12px;
            }
          }
        }
      }
    }
  }

  // 预览对话框
  .image-preview-dialog {
    .preview-toolbar {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 12px 0;
      border-bottom: 1px solid #ebeef5;
      margin-bottom: 20px;

      .toolbar-left {
        .image-info {
          font-size: 14px;
          color: #303133;
          font-weight: 500;
        }
      }

      .toolbar-right {
        display: flex;
        gap: 8px;
      }
    }

    .preview-container {
      display: flex;
      align-items: center;
      justify-content: center;
      min-height: 400px;
      max-height: 60vh;
      overflow: hidden;
      background-color: #f5f7fa;
      border-radius: 4px;

      .preview-image {
        transition: transform 0.3s ease;
        cursor: grab;

        &:active {
          cursor: grabbing;
        }
      }
    }

    .preview-nav {
      margin-top: 20px;
      padding-top: 20px;
      border-top: 1px solid #ebeef5;

      .nav-thumbnails {
        display: flex;
        gap: 8px;
        justify-content: center;
        flex-wrap: wrap;

        .nav-thumbnail {
          width: 60px;
          height: 60px;
          border-radius: 4px;
          overflow: hidden;
          border: 2px solid transparent;
          cursor: pointer;
          transition: border-color 0.3s ease;

          &.active {
            border-color: #409eff;
          }

          img {
            width: 100%;
            height: 100%;
            object-fit: cover;
          }
        }
      }
    }
  }
}
</style>
